-- LuaTools需要PROJECT和VERSION这两个信息
PROJECT = '	TEST'
VERSION = '1.0.0'

log.info("main", PROJECT, VERSION)

-- sys库是标配
_G.sys = require("sys")

if wdt then
    --添加硬狗防止程序卡死，在支持的设备上启用这个功能
    wdt.init(15000)--初始化watchdog设置为15s
    sys.timerLoopStart(wdt.feed, 10000)--10s喂一次狗
end
--------------------------单灯LED闪烁实验--------------------------------
--[[
local LED1 = gpio.setup(pin.PB08, 0) -- PB0输出模式
sys.taskInit(function()
    while 1 do
        log.info("LED开启")
        LED1(0)
        sys.wait(1000)
        log.info("LED关闭")
        LED1(1)
        sys.wait(1000)
    end
end)
]]--
--------------------------- 跑马灯实验-----------------------------------
--[[
-- 下面的GPIO引脚编号，请根据实际需要进行更改！
-- Air101开发板的3个LED分别为 PB08/PB09/PB10
-- Air103开发板的3个LED分别为 PB24/PB25/PB26
-- Air105开发板的3个LED分别为 PD14/PD15/PC3
local LEDA = gpio.setup(pin.PB08, 0, gpio.PULLUP) -- PB8输出模式,内部上拉
local LEDB = gpio.setup(pin.PB09, 0, gpio.PULLUP) -- PB9输出模式,内部上拉
local LEDC = gpio.setup(pin.PB10, 0, gpio.PULLUP) -- PB10输出模式,内部上拉
sys.taskInit(function()
    local count = 0
    while 1 do
        sys.wait(500)
        -- 一闪一闪亮晶晶
        LEDA(count % 3 == 0 and 1 or 0)
        LEDB(count % 3 == 1 and 1 or 0)
        LEDC(count % 3 == 2 and 1 or 0)
        log.info("gpio", "Go Go Go", count, rtos.bsp())
        count = count + 1
    end
end)
]]--
--------------------------------- 按键实验-------------------------------
--[[
local button_timer_outtime = 10 --按键定时器: 10ms
local button_shake_time = 1     --按键消抖时间: button_shake_time*button_timer_outtime
local button_long_time = 100    --按键长按时间: button_shake_time*button_timer_outtime
local button_state = 0 --按键状态（松开0，按下1）
local button_cont = 0
local LEDA = gpio.setup(pin.PB08, 0, gpio.PULLUP) -- PB8输出模式,内部上拉
button = gpio.setup(pin.PA00,	--button获取电平的闭包，button()表示状态
function()						--中断模式
	LEDA(1-gpio.get(pin.PB08))
end,
gpio.PULLUP,gpio.FALLING)  --按键按下接地，因此需要上拉
sys.taskInit(function()
    while 1 do
		if button() == 0 then   --按键当前时刻为低电平（被按下） 此处根据上下拉选择0/1
			button_cont = button_cont + 1   --计数值加一
			if button_cont > button_long_time then  --计数次数大于长按阈值
				print("long passing")
			end
		else --按键当前时刻电平与状态不符
			if button_cont < button_shake_time then  --计数次数小于抖动阈值（视为抖动）
			else
				if button_cont < button_long_time then  --计数次数小于长按阈值
					print("pass")     --正常按键情况
				else
					print("long pass")  --长按情况
				end
			end
			button_cont = 0   --计数清零
			button_state = 0  --松开状态
		end
		sys.wait(button_timer_outtime)
    end
end)
]]--

--另一种写法
--[[
button_timer = sys.timerLoopStart(function()
	if button() == 0 then   --按键当前时刻为低电平（被按下） 此处根据上下拉选择0/1
		button_cont = button_cont + 1   --计数值加一
		if button_cont > button_long_time then  --计数次数大于长按阈值
			print("long pass")
		end
	else --按键当前时刻电平与状态不符
		if button_cont < button_shake_time then  --计数次数小于抖动阈值（视为抖动）
		else
			if button_cont < button_long_time then  --计数次数小于长按阈值
				print("pass")     --正常按键情况
			else
				print("long pass......")  --长按情况
			end
		end
		button_cont = 0   --计数清零
		button_state = 0  --松开状态
	end
end,button_timer_outtime) --每次轮询间隔
--]]
----------------------------PWM控制LED灯实验-----------------------------
--[[
-- Air101
-- PWM4 --> PA7
-- PWM3 --> PB3
-- PWM2 --> PB2
-- PWM1 --> PB1
-- PWM0 --> PB0
-- https://wiki.luatos.com/api/pwm.html
sys.taskInit(function()
    while 1 do
        -- 仿呼吸灯效果（需要外接LED）
        log.info("pwm", ">>>>>")
        for i = 100,1,-1 do 
            pwm.open(4, 1000, 100-i) -- 打开PWM4, 频率1000hz, 占空比0-100
            -- pwm.open(5, 1000, 31, 0, 256) -- 打开PWM4, 频率1000Hz, 单次输出，分频（占空比）为 31/256
            sys.wait(20)
        end
        sys.wait(1000)
        for i = 100,1,-1 do 
            pwm.open(4, 1000, i)
            sys.wait(20)
        end
        sys.wait(1000)
    end
end)
]]--
--------------------------PWM控制舵机实验--------------------------------
--[[
-- SG90舵机 周期20ms  脉冲宽度0.5ms（0°）~2.5ms（180°）
-- 直接连开发板需要接5V
-- Air101不支持分频系数为1000
sys.taskInit(function()
    while 1 do
        log.info("Servo", ">>>>>")
        for i = 8,32,1 do 
            pwm.open(4, 50, i, 0 ,256) -- 打开PWM4, 频率50hz, 单次输出，分频（占空比）为 i/256
            sys.wait(20)
        end
        sys.wait(1000)
        for i = 32,8,-1 do 
            pwm.open(4, 50, i, 0 ,256) -- 打开PWM4, 频率50hz, 单次输出，分频（占空比）为 i/256
            sys.wait(20)
        end
        sys.wait(1000)
        pwm.open(4, 50, 32, 0 ,256)
        sys.wait(2000)
        pwm.open(4, 50, 8, 0 ,256)
        sys.wait(2000)
    end
end)
]]--
---------------------------UART串口实验----------------------------------
--[[
-- 实验过程：使用串口命令on/off控制LED灯的亮灭，串口接受的数据将发送返回
-- 串口库文档：https://wiki.luatos.com/api/uart.html
local LED1 = gpio.setup(pin.PB08, 0) -- PB0输出模式

local uartid,sendQueue = 1,{}   -- 根据实际设备选取不同的uartid,串口读缓冲区

-- 串口超时，串口准备好后发布的消息
-- 例子是100ms，按需求改
local uartimeout, recvReady = 100, "UART_RECV"
--初始化
uart.setup(
    uartid,--串口id
    115200,--波特率
    8,--数据位
    1--停止位
)

uart.on(uartid, "receive", function(id, len) -- 注册串口中断服务函数，中断类型为接收中断，function内固定参数
    local s
    while true do -- 保证读完不能丢包
        s = uart.read(id, len)
        if #s == 0 then break end -- #s是取字符串的长度,等于0表示接受完成，退出
        table.insert(sendQueue, s)  -- 读取到的数据传入串口读缓冲区
    end
    sys.timerStart(sys.publish, uartimeout, recvReady)  -- 接收完成uartimeout时间后发布recvReady消息
end)

-- publish和subscribe结合使用，订阅到发布的消息后执行函数
-- 向串口发送收到的字符串
sys.subscribe(recvReady, function()      
    --拼接所有收到的数据
    local str = table.concat(sendQueue)
    -- 串口的数据读完后清空缓冲区
    sendQueue = {}
    --注意打印会影响运行速度，调试完注释掉
    --log.info("uartTask.read length", #str, str:sub(1,100))
    uart.write(uartid,str) --回复
    if str == "on" then 
        LED1(1)
    elseif str == "off" then
        LED1(0)
    end
    --在这里处理接收到的数据，这是例子
end)

-- 并非所有设备都支持sent事件(实测Air101可实现该事件中断)
uart.on(uartid, "sent", function(id)  -- 注册串口中断服务函数，中断类型为发送完成中断
    log.info("uart"..id, "sent")
end)
]]--
--------------------------------ADC实验---------------------------------
--[[
-- ADC库文档：https://wiki.luatos.com/api/adc.html
-- Air101  输入电压范围0~2.4v
-- ADC编号   功能
--   0     ADC0->PA1  
--   1     ADC1->PA4  
--   10    CPU温度
--   11    内部电压
local adc0,adc_temp,vbat
local LED1 = gpio.setup(pin.PB08, 0) -- PB0输出模式
sys.taskInit(function()
    while 1 do
        adc.open(0)  -- 模块上的ADC0脚-PA1, 0~2.4v,不要超过范围使用!!!   返回两个int值，原始值和电压（mv）/温度值（mC）
        adc.open(10) -- CPU温度
        adc.open(11) -- VBAT电压,最新代码才支持
        sys.wait(500)

        adc0 = {adc.read(0)}
        adc_temp = {adc.read(10)}
        vbat = {adc.read(11)}

        if adc_temp[2] > 40000 then
            LED1(1)
        else
            LED1(0)
        end

        log.info("adc", "adc0: ".. (adc0[2]/1000).."V")
        log.info("adc", "temp: ".. (adc_temp[2]/1000).."°C")
        log.info("adc", "vbat: ".. (vbat[2]/1000).."V")
        -- 使用完毕后关闭,可以使得休眠电流更低.
        adc.close(0)
        adc.close(1)
        adc.close(10)
        adc.close(11)
        sys.wait(500)     
    end
end)
--]]
-----------------------------I2C实验（MPU6050库方法)---------------------
--[[
--PA1为SCL引脚，PA4为SDA引脚
--需要添加mpu6xxx.lua文件
--库内容：https://gitee.com/openLuat/LuatOS/blob/master/script/libs/mpu6xxx/mpu6xxx.lua
--支持mpu6500,mpu6050,mpu9250,icm2068g,icm20608d,自动判断器件id,只需要配置i2c id就可以
--注意:因使用了sys.wait()所有api需要在协程中使用
local mpu6xxx = require "mpu6xxx"
i2cid = 0
i2c_speed = i2c.FAST
sys.taskInit(function()
    i2c.setup(i2cid,i2c_speed)
    mpu6xxx.init(i2cid)--初始化,传入i2c_id
    while 1 do
        sys.wait(100)
        local temp = mpu6xxx.get_temp()--获取温度
        log.info("6050temp", temp)
        local accel = mpu6xxx.get_accel()--获取加速度 单位: mg
        log.info("6050accel", "accel.x",accel.x,"accel.y",accel.y,"accel.z",accel.z)
        local gyro = mpu6xxx.get_gyro()--获取陀螺仪 deg / 10s
        log.info("6050gyro", "gyro.x",gyro.x,"gyro.y",gyro.y,"gyro.z",gyro.z)
    end
end)
]]--
-----------------------------I2C实验(mp6050)----------------------------
local i2cslaveaddr = 0x68  -- mpu6050 AD0引脚不接通信地址默认为0x68
local i2cid = 0    -- 初始化i2c，使用设备id为0(id可以自己定义)
local buffer     --读取数值
local temp       --温度
local accel={x=nil,y=nil,z=nil}   --加速度
local gyro={x=nil,y=nil,z=nil}    --陀螺仪

-- MPU6050数值转换系数
local MPU6050_ACCEL_SEN           =   16384
local MPU6050_GYRO_SEN            =   1310
local MPU6050_TEMP_SEN            =   340
local MPU6050_TEMP_OFFSET         =   36.5

-- MPU6050数据寄存器地址（查手册）
local MPU6050_RA_ACCEL_XOUT_H     =   0x3B
local MPU6050_RA_ACCEL_XOUT_L     =   0x3C
local MPU6050_RA_ACCEL_YOUT_H     =   0x3D
local MPU6050_RA_ACCEL_YOUT_L     =   0x3E
local MPU6050_RA_ACCEL_ZOUT_H     =   0x3F
local MPU6050_RA_ACCEL_ZOUT_L     =   0x40
local MPU6050_RA_TEMP_OUT_H       =   0x41
local MPU6050_RA_TEMP_OUT_L       =   0x42
local MPU6050_RA_GYRO_XOUT_H      =   0x43
local MPU6050_RA_GYRO_XOUT_L      =   0x44
local MPU6050_RA_GYRO_YOUT_H      =   0x45
local MPU6050_RA_GYRO_YOUT_L      =   0x46
local MPU6050_RA_GYRO_ZOUT_H      =   0x47
local MPU6050_RA_GYRO_ZOUT_L      =   0x48

-- MPU6050配置寄存器地址（查手册）
local MPU6050_RA_PWR_MGMT_1     =   0x6B	--电源管理，典型值：0x00(正常启用)
local MPU6050_RA_SMPLRT_DIV		=   0x19	--陀螺仪采样率，典型值：0x07(125Hz)
local MPU6050_RA_CONFIG			=   0x1A	--低通滤波频率，典型值：0x06(5Hz)
local MPU6050_RA_GYRO_CONFIG	=   0x1B	--陀螺仪自检及测量范围，典型值：0x18(不自检，2000deg/s)
local MPU6050_RA_ACCEL_CONFIG	=   0x1C	--加速计自检、测量范围及高通滤波频率，典型值：0x01(不自检，2G，5Hz)
local MPU6050_RA_FIFO_EN        =   0x23    --fifo使能
local MPU6050_RA_INT_PIN_CFG    =   0x37    --int引脚有效电平
local MPU6050_RA_INT_ENABLE     =   0x38    --中断使能
local MPU6050_RA_USER_CTRL      =   0x6A    --MPU6050的主/从机模式，典型值：0x00(从机模式)
local MPU6050_RA_PWR_MGMT_1     =   0x6B
local MPU6050_RA_PWR_MGMT_2     =   0x6C



sys.taskInit(function()
    -- 初始化i2c，setup用的是开发板上的i2c引脚，也可以通过i2c.createSoft创建软件i2c对象
    if i2c.setup(i2cid, i2c.FAST, i2cslaveaddr) == 1 then   
        log.info("i2c"..i2cid.." exist")    
    else
        i2c.close(i2cid) -- 关掉
    end

    -- 初始化mpu6050
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_PWR_MGMT_1, 0x80})    --复位
    sys.wait(100)
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_PWR_MGMT_1, 0x00})    --唤醒
    sys.wait(100)
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_SMPLRT_DIV, 0x07})    --陀螺仪采样率，典型值：0x07(125Hz)
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_CONFIG, 0x06})        --低通滤波频率，典型值：0x06(5Hz)
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_GYRO_CONFIG, 0x18})   --陀螺仪自检及测量范围，典型值：0x18(不自检，2000deg/s)
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_ACCEL_CONFIG, 0x01})  --加速计自检、测量范围及高通滤波频率，典型值：0x01(不自检，2G，5Hz)
    --i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_FIFO_EN, 0x00})     --关闭fifo
    --i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_INT_ENABLE, 0x00})  --关闭所有中断
    --i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_USER_CTRL, 0x00})   --I2C主模式关闭
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_PWR_MGMT_1, 0x01})    --设置x轴的pll为参考
    i2c.send(i2cid, i2cslaveaddr, {MPU6050_RA_PWR_MGMT_2, 0x00})    --加速度计与陀螺仪开启
    log.info("mpu6050 init_ok")

    while 1 do
        sys.wait(1000)

        --温度原始数据获取 
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_TEMP_OUT_H)         --获取温度的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)                   --获取2字节数据
        _, temp = pack.unpack(buffer, ">h")                         --将字符串解包成大端编码short (2字节)
        --计算温度的数据 单位：°C
        temp = temp / MPU6050_TEMP_SEN + MPU6050_TEMP_OFFSET
        log.info("6050temp", temp)

        --陀螺仪测角速度的，加速度传感器测角加速度的，二者数据通过算法就可以得到PITCH、YAW、ROLL角

        --加速度原始数据获取 
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_ACCEL_XOUT_H)       --获取X方向加速度的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)                   
        _,accel.x = pack.unpack(buffer,">h")
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_ACCEL_YOUT_H)       --获取Y方向加速度的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)                   
        _,accel.y = pack.unpack(buffer,">h")
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_ACCEL_ZOUT_H)       --获取Z方向加速度的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)                   
        _,accel.z = pack.unpack(buffer,">h")
        --计算加速度计的数据 单位: mg
        accel.x = accel.x*1000/MPU6050_ACCEL_SEN
        accel.y = accel.y*1000/MPU6050_ACCEL_SEN
        accel.z = accel.z*1000/MPU6050_ACCEL_SEN
        log.info("6050accel", "accel.x",accel.x,"accel.y",accel.y,"accel.z",accel.z)

        --陀螺仪原始数据获取 
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_GYRO_XOUT_H)        --获取X方向陀螺仪的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)
        _,gyro.x = pack.unpack(buffer,">h")
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_GYRO_YOUT_H)        --获取Y方向陀螺仪的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)
        _,gyro.y = pack.unpack(buffer,">h")
        i2c.send(i2cid, i2cslaveaddr,MPU6050_RA_GYRO_ZOUT_H)        --获取Z方向陀螺仪的地址
        buffer = i2c.recv(i2cid, i2cslaveaddr, 2)
        _,gyro.z = pack.unpack(buffer,">h")
        --计算陀螺仪的数据 单位：deg/10s
        gyro.x = gyro.x*100/MPU6050_GYRO_SEN
        gyro.y = gyro.y*100/MPU6050_GYRO_SEN
        gyro.z = gyro.z*100/MPU6050_GYRO_SEN
        log.info("6050gyro", "gyro.x",gyro.x,"gyro.y",gyro.y,"gyro.z",gyro.z)
    end
end)

------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------------------------------------------------
------------------------------PWM捕获-----------------------------------




sys.run()






----------------------------学习笔记------------------------------------
--[[
    sys.timerLoopStart(fnc,ms,...)   开启一个循环定时器

    传入值类型  释义
    param      fnc定时器回调函数
    number     ms整数，最大定时126322567ms
    param      ...可变整数fnc的参数

    返回值
    number    定时器ID，如果失败，返回nil
------------------------------------------------------------------------
    pack - 打包和解包格式串
    https://wiki.luatos.com/api/pack.html?highlight=pack

--]]
